package smallChanges.statements;

import smallChanges.Tokenization.CodeRange2D;

public class StatementMappingEntry implements Comparable<StatementMappingEntry>{
	
	public enum StatementMappingStatus {VALID, PROBABLE, POSSIBLE, INVALID};
	
	private double normalizedEditDistance;
	private double normalizedTokenEditDistance;
	private int crossings;
	private Statement leftStatement;
	private Statement rightStatement;
	
	private StatementMappingStatus status;
	
	public String toString()
	{
	    if (normalizedEditDistance>0.0 && !isPureAdd() && !isPureDelete()) {
	        // XXX Change
	        // TODO: get only the raw text of the statement, 
	        // not line/col info
	        return 
	            leftStatement.getBeginLine()+","+leftStatement.getEndLine()+"c"+
	            rightStatement.getBeginLine()+","+rightStatement.getEndLine()+
	            " (" +status+" match with score: " +normalizedEditDistance+")\n"+
	            "< "+leftStatement + "\n---\n"+
	            "> "+rightStatement;
	    }
//	    if (normalizedTokenEditDistance>0.0) {
//	        // TODO: token diff should use cosine difference algo
//	        return "token ("+normalizedEditDistance+"):\n"+
//            "> "+leftStatement + "\n< "+rightStatement;
//	    }
	    //TODO: handle deletes on both sides
	    else if (isPureAdd()) {
	        // add
	        return "a"+rightStatement.getBeginLine()+","+rightStatement.getEndLine()+
	        "\n"+
	        "> "+rightStatement;
	    } else if (isPureDelete()){
	        // delete
	        return leftStatement.getBeginLine()+","+leftStatement.getEndLine()+
	        "d\n"+
	        "< "+leftStatement;
	    }
	    return "";
	}

	public StatementMappingEntry (Statement leftSt, Statement rightSt,  int cross, StatementMappingStatus status)
	{
		leftStatement = leftSt;
		rightStatement = rightSt;
		normalizedEditDistance = 1;
		normalizedTokenEditDistance = 1;
		if( leftSt != null && rightSt != null)
		{
		    normalizedEditDistance = leftSt.getNormalizedLevenshteinEditDistance(rightSt);
		    normalizedTokenEditDistance = leftSt.getNormalizedLevenshteinTokenEditDistance(rightSt);
		}
		crossings = cross;
		this.status = status;
	}
	
	public int compareTo(StatementMappingEntry other)
	{
		int result = 0;
		
		CodeRange2D left,right;
		
		left = (CodeRange2D) this.getLeftStatement();
        right = (CodeRange2D) other.getLeftStatement();
		
        result =left.compareTo(right); 
        if( result == 0 )
        {
            left = (CodeRange2D) this.getRightStatement();
            right = (CodeRange2D) other.getRightStatement();
            result =left.compareTo(right); 
        }
        return result;
		/*if( leftStatement.getBeginLine() < other.getLeftStatement().getBeginLine() )
		{
			result = -1;
		}
		if( leftStatement.getBeginLine() > other.getLeftStatement().getBeginLine())
		{
			result = 1;
		}
						
		if( leftStatement.getBeginLine() == other.getLeftStatement().getBeginLine() )
		{
		    if( leftStatement.getBeginColumn() < other.getLeftStatement().getBeginColumn())
		    {
		        result = -1;
		    }
		    else if(leftStatement.getBeginColumn() > other.getLeftStatement().getBeginColumn())
		    {
		        result = 1;
		    }
		    else if( rightStatement.getBeginLine() < other.getRightStatement().getBeginLine())
			{
				result = -1;
			}
			else if( rightStatement.getBeginLine() > other.getRightStatement().getBeginLine())
			{
				result = 1;
			}
			else if( rightStatement.getBeginColumn() < other.getRightStatement().getBeginColumn())
            {
                result = -1;
            }
			else if( rightStatement.getBeginColumn() > other.getRightStatement().getBeginColumn())
            {
                result = 1;
            }
		}
		return result;
		*/		
	}
	
	public boolean equals(Object other)
	{
		StatementMappingEntry right = (StatementMappingEntry) other;
		
		return leftStatement.getBeginLine() == right.getLeftStatement().getBeginLine() && rightStatement.getBeginLine() == right.getRightStatement().getBeginLine(); 
	}
	
	public StatementMappingEntry()
	{
		normalizedEditDistance = -1.0;
		normalizedTokenEditDistance = -1.0;
		crossings = -1;
		status = StatementMappingStatus.INVALID;
	}

	public double getNormalizedEditDistance() {
		return normalizedEditDistance;
	}

	public void setNormalizedEditDistance(double normalizedEditDistance) {
		this.normalizedEditDistance = normalizedEditDistance;
	}

	public double getNormalizedTokenEditDistance() {
		return normalizedTokenEditDistance;
	}

	public void setNormalizedTokenEditDistance(double normalizedTokenEditDistance) {
		this.normalizedTokenEditDistance = normalizedTokenEditDistance;
	}

	public int getCrossings() {
		return crossings;
	}

	public void setCrossings(int crossings) {
		this.crossings = crossings;
	}

	public StatementMappingStatus getStatus() {
		return status;
	}

	public void setStatus(StatementMappingStatus status) {
		this.status = status;
	}

	public Statement getLeftStatement() {
		return leftStatement;
	}

	public void setLeftStatement(Statement leftStatement) {
		this.leftStatement = leftStatement;
	}

	public Statement getRightStatement() {
		return rightStatement;
	}

	public void setRightStatement(Statement rightStatement) {
		this.rightStatement = rightStatement;
	}
	
	public boolean isPureAdd()
	{
	    return leftStatement.getEndLine() == -1;
	}
	public boolean isPureDelete()
    {
        return rightStatement.getEndLine() == -1;        
    }
}
